﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;
using Dispatcher.LogicalModels;
using Dispatcher.ViewModels.Base;
using Repository;

namespace Dispatcher.ViewModels
{
    /// <summary>
    /// Place Timetable View Model.
    /// </summary>
    public class PlaceTimetableViewModel : ViewModelBase
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="PlaceTimetableViewModel"/> class.
        /// </summary>
        /// <param name="modelContainer">The model container.</param>
        public PlaceTimetableViewModel(ModelContainer modelContainer)
        {
            CommandBindings.Add(new CommandBinding(ApplicationCommands.Open, LoadExecuted));
            ModelContainer = modelContainer;
            GenerateStandartPairs();
        }

        /// <summary>
        /// Gets or sets the model container.
        /// </summary>
        /// <value>
        /// The model container.
        /// </value>
        public ModelContainer ModelContainer { get; set; }

        /// <summary>
        /// Gets or sets the pairs.
        /// </summary>
        /// <value>
        /// The pairs.
        /// </value>
        public List<Event> StandartPairs { get; set; }

        /// <summary>
        /// Gets or sets the timetable.
        /// </summary>
        /// <value>
        /// The timetable.
        /// </value>
        public List<DailyEvents> Timetable { get; set; }

        private DateTime _fromDate;

        /// <summary>
        /// Gets or sets from date.
        /// </summary>
        /// <value>
        /// From date.
        /// </value>
        public DateTime FromDate
        {
            get { return _fromDate; }
            set
            {
                while (value.Date.DayOfWeek != DayOfWeek.Monday)
                {
                    value = value.AddDays(-1);
                }
                _fromDate = value;
            }
        }

        /// <summary>
        /// Gets or sets to date.
        /// </summary>
        /// <value>
        /// To date.
        /// </value>
        public DateTime ToDate { get; set; }

        /// <summary>
        /// Gets or sets the person group.
        /// </summary>
        /// <value>
        /// The person group.
        /// </value>
        public PersonGroup PersonGroup { get; set; }

        /// <summary>
        /// Generates the standart pairs.
        /// </summary>
        private void GenerateStandartPairs()
        {
            var now = DateTime.Now.Date;
            var ev1 = new Event { StartTime = now.Add(new TimeSpan(8, 0, 0)), EndTime = now.Add(new TimeSpan(9, 35, 0)) };
            var ev2 = new Event { StartTime = now.Add(new TimeSpan(9, 35, 0)), EndTime = now.Add(new TimeSpan(9, 45, 0)) };
            var ev3 = new Event { StartTime = now.Add(new TimeSpan(9, 45, 0)), EndTime = now.Add(new TimeSpan(11, 20, 0)) };
            var ev4 = new Event { StartTime = now.Add(new TimeSpan(11, 20, 0)), EndTime = now.Add(new TimeSpan(11, 40, 0)) };
            var ev5 = new Event { StartTime = now.Add(new TimeSpan(11, 40, 0)), EndTime = now.Add(new TimeSpan(13, 15, 0)) };
            var ev6 = new Event { StartTime = now.Add(new TimeSpan(13, 15, 0)), EndTime = now.Add(new TimeSpan(13, 25, 0)) };
            var ev7 = new Event { StartTime = now.Add(new TimeSpan(13, 25, 0)), EndTime = now.Add(new TimeSpan(15, 00, 0)) };
            var ev15 = new Event { StartTime = now.Add(new TimeSpan(15, 00, 0)), EndTime = now.Add(new TimeSpan(15, 20, 0)) };
            var ev8 = new Event { StartTime = now.Add(new TimeSpan(15, 20, 0)), EndTime = now.Add(new TimeSpan(16, 55, 0)) };
            var ev9 = new Event { StartTime = now.Add(new TimeSpan(16, 55, 0)), EndTime = now.Add(new TimeSpan(17, 05, 0)) };
            var ev10 = new Event { StartTime = now.Add(new TimeSpan(17, 05, 0)), EndTime = now.Add(new TimeSpan(18, 35, 0)) };
            var ev11 = new Event { StartTime = now.Add(new TimeSpan(18, 35, 0)), EndTime = now.Add(new TimeSpan(18, 45, 0)) };
            var ev12 = new Event { StartTime = now.Add(new TimeSpan(18, 45, 0)), EndTime = now.Add(new TimeSpan(20, 20, 0)) };
            var ev13 = new Event { StartTime = now.Add(new TimeSpan(20, 20, 0)), EndTime = now.Add(new TimeSpan(20, 30, 0)) };
            var ev14 = new Event { StartTime = now.Add(new TimeSpan(20, 30, 0)), EndTime = now.Add(new TimeSpan(22, 00, 0)) };

            StandartPairs = new List<Event>
                        {
                            ev1,
                            ev2,
                            ev3,
                            ev4,
                            ev5,
                            ev6,
                            ev7,
                            ev15,
                            ev8,
                            ev9,
                            ev10,
                            ev11,
                            ev12,
                            ev13,
                            ev14,
                        };
        }

        /// <summary>
        /// Searches this instance.
        /// </summary>
        /// <returns>Finded places.</returns>
        private IEnumerable<Place> SearchFreePlaces(Event ev)
        {
            var fromDate = ev.StartTime.Date;
            var toDate = ev.EndTime.Date;

            var fromTime = ev.StartTime - fromDate;
            var toTime = ev.EndTime - toDate;

            var allPlaces = new List<Place>();

            for (var date = fromDate; date <= toDate; date = date.AddDays(1))
            {
                var from = date + fromTime;
                var to = date + toTime;
                var places =
                    ModelContainer.PlaceSet.Where(
                        place =>
                        !place.Event.Any(
                            e =>
                            (from == e.StartTime && e.EndTime == to) ||
                            (from < e.StartTime && e.StartTime < to) ||
                            (from < e.EndTime && e.EndTime < to))).ToList();

                allPlaces.AddRange(places);
            }

            return allPlaces;
        }

        /// <summary>
        /// Loads the executed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="executedRoutedEventArgs">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void LoadExecuted(object sender, ExecutedRoutedEventArgs executedRoutedEventArgs)
        {
            LoadData();
        }

        /// <summary>
        /// Loads the data.
        /// </summary>
        public void LoadData()
        {
            Timetable = new List<DailyEvents>();
            for (var date = FromDate; date <= ToDate; date = date.AddDays(1))
            {
                Timetable.Add(new DailyEvents(date, ModelContainer, PersonGroup.Place.ToList()));
            }
        }
    }
}
